package cz.vse;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 
 * @author  VERNER Jan
 * @version 21.3.2012
 */
public class FrontControllerFilter implements Filter
{
//== CONSTANTS & FIELDS (STATIC) ===============================================
//== CONSTANTS & FIELDS ========================================================

//== NON-PRIVATE METHODS (STATIC) ==============================================
//== NON-PRIVATE METHODS =======================================================
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // do nothing
    }

    /**
     * Směruje zpracování akcí do příslušných privátních metod.
     * Filter je namapován na /*, tudíž všechny příchozí requesty jdou nejprve
     * tudy.
     */
    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain filterChain)
            throws IOException, ServletException
    {
        // Přetypujeme na HTTP objekty
        HttpServletRequest httpRequest  = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        // sdělíme kontejneru, v jakém kódování očekáváme data od klienta
        request.setCharacterEncoding("UTF-8");
        
        // --- PARAMETER INFO ---      
        Map<String, String[]> pars = httpRequest.getParameterMap(); 
        Iterator<String[]> it = pars.values().iterator();
        for (String key : pars.keySet()) {
            System.out.println("KEY: " + key + ", VAL: " + it.next()[0]);
        }
        // --- /INFO ---

        // Větvení podle akce.
        String action = httpRequest.getParameter("action");
        
        if ("doLogin".equals(action)) {
            doLogin(httpRequest, httpResponse);
        } else if ("doLogout".equals(action)) {
            doLogout(httpRequest, httpResponse);
        } else {
            noAction(httpRequest, httpResponse, filterChain);
        }
    }

    @Override
    public void destroy() {
        // do nothing
    }
    

//== PRIVATE METHODS (STATIC) ==================================================
//== PRIVATE METHODS ===========================================================
    
    /**
     * Reaguje na akci doLogin. Z dotazu zjistí nick. Pokud
     * není přítomen, vrátí řízení na login.jsp. Jinak
     * vytvoří cookie a nastaví do něj nick z dotazu. Každý
     * další dotaz by měl nést toto cookie. Přítomnost cookie
     * v dotazu se chápe jako identifikace aktuálního uživatele.
     */
    private void doLogin(HttpServletRequest request,
                         HttpServletResponse response)
            throws IOException, ServletException
    {
        // login.jsp předává parametr nick
        String nickname = request.getParameter("nick");
        if ("".equals(nickname)) {
            forwardToLogin(request, response);
            return;
        }
        // Název cookie je cookieNick, hodnota je vlastní nick
        Cookie cookie = new Cookie("cookieNick", nickname);

        // Nastavíme 24 hodin platnost.
        //cookie.setMaxAge(60 * 60 * 24);

        // Hodnota -1 by způsobila, že cookie platí pouze do zavření prohlížeče.
        cookie.setMaxAge(-1);
        response.addCookie(cookie);

        // Přesměrujeme aktuální dotaz na emailový formulář
        response.sendRedirect("mailForm.jsp");
    }
    
    /**
     * Předává řízení na <code>login.jsp</code>.
     */
    private void forwardToLogin(HttpServletRequest request,
                                HttpServletResponse response)
            throws ServletException, IOException
    {
        // Získáme dispečera stránky
        RequestDispatcher loginDispatcher =
                request.getRequestDispatcher("login.jsp");
        loginDispatcher.forward(request, response);
    }
    
    /**
     * Odhlašuje uživatele smazáním cookie v prohlížeči.
     */
    private void doLogout(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException
    {
        // Zkusíme najít cookie, které chceme smazat
        Cookie cookieNick = findCookie("cookieNick", request);
        if (cookieNick != null) {
            // Nastavení maxAge na 0 vede ke smazání cookie 
            cookieNick.setMaxAge(0);
            response.addCookie(cookieNick);
        }
        
        HttpSession session = request.getSession(false); // nevytvářet novou session pokud neexistuje
        if (session != null) {
            session.invalidate();
        }

        // Předáme řízení login.jsp
        forwardToLogin(request, response);
    }
    
    /**
     * Hledá cookie s názvem <code>cookieNick</code>
     *
     * @param request dotaz
     * @return cookie nebo null
     */
    private Cookie findCookie(String name, HttpServletRequest request)
    {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    return cookie;
                }
            }
        }
        return null;
    }
    
    /**
     * Voláno pokud v dotazu není specifikovaná akce
     */
    private void noAction(HttpServletRequest request,
                          HttpServletResponse response,
                          FilterChain filterChain)
            throws IOException, ServletException
    {
        // Zkusíme najít cookie 'cookieNick'
        Cookie cookieNick = findCookie("cookieNick", request);
        if (cookieNick != null) {
            // Cookie přišlo -> uživatel je přihlášen.
            
            // Nastavíme nick uživatele jako atribut session.
            HttpSession session = request.getSession();
            String nickName = cookieNick.getValue();
            // Nastavení pouze pokud ještě není v session.
            if (!nickName.equals(session.getAttribute("user"))) {
                session.setAttribute("user", nickName);
            }

            // Předáme řízení standardním způsobem
            filterChain.doFilter(request, response);
        }
        else {
            // Cookie se nenašlo -> uživatel není přihlášen.
            // Předáme řízení na login stránku.
            forwardToLogin(request, response);
        }
    }

        
//== NESTED TYPES ==============================================================

//== MAIN METHOD (TEST) ========================================================

//    /**
//     * @param args the command line arguments
//     */
//    public static void main(String[] args) {
//        // TODO code application logic here
//    }
    
}
